#pragma once

#include "Base/Tests/Test.Application.h"

#undef  APP_NAME
#define APP_NAME	TestLocation
#undef  APP_BASE
#define APP_BASE	TestApp


class APP_NAME : public APP_BASE
{
public:
	APP_NAME (IPlatform *platform, EDevice::type deviceType) :
		APP_BASE( platform, deviceType )
	{
	}


	void OnEnter () override
	{
		Test0();
		Test1();
		Test2();
		Test3();
	}


	void Test0 ()
	{
		GeoLocation	loc0,
					loc1;

		loc0.FromDegrees( 30.2231081, 59.9768738 );
		loc1.FromDegrees( 30.3380596, 59.9541345 );

		double	dist0 = GeoLocation::_Haversine( loc0, loc1 );
		double	dist1 = GeoLocation::_SphericalLawOfCosines( loc0, loc1 );
		double	dist2 = GeoLocation::_EquirectangularApproximation( loc0, loc1 );

		double	d01	= dist0 - dist1;
		double	d02 = dist0 - dist2;

		//ASSERT( IsZero( d01 ) );
		//ASSERT( IsZero( d02 ) );


		dvec2	delta = loc0.Vector( loc1 );
		dvec2	v( 6.4, 2.4 );

		double	len  = v.Length() * 1000.0;
		double	dist = delta.Length(); 
	}


	void Test1 ()
	{
		GeoLocation	loc,
					prev;
		double		dist0 = 0.0,
					dist1 = 0.0,
					dist2 = 0.0;

		for (int i = -18; i <= 18; ++i)
		{
			loc.FromDegrees( double(i) * 10.0, 0.0 );
			
			if ( i == -18 )
			{
				prev = loc;
				continue;
			}

			dist0 += GeoLocation::_Haversine( loc, prev );
			dist1 += GeoLocation::_SphericalLawOfCosines( loc, prev );
			dist2 += GeoLocation::_EquirectangularApproximation( loc, prev );
			prev   = loc;
		}

		const double	len = 2.0 * Pi<double>() * GeoLocation::GetEarthMeanRadius();

		dist0 /= len;
		dist1 /= len;
		dist2 /= len;

		//ASSERT( Equals( dist0, 1.0 ) );
		//ASSERT( Equals( dist1, 1.0 ) );
		//ASSERT( Equals( dist2, 1.0 ) );
	}


	void Test2 ()
	{
		GeoLocation	loc,
					prev;
		double		dist0 = 0.0,
					dist1 = 0.0,
					dist2 = 0.0;

		for (int i = -9; i <= 9; ++i)
		{
			loc.FromDegrees( 0.0, double(i) * 10.0 );

			if ( i == -9 )
			{
				prev = loc;
				continue;
			}
			
			dist0 += GeoLocation::_Haversine( loc, prev );
			dist1 += GeoLocation::_SphericalLawOfCosines( loc, prev );
			dist2 += GeoLocation::_EquirectangularApproximation( loc, prev );
			prev   = loc;
		}

		const double	len = Pi<double>() * GeoLocation::GetEarthMeanRadius();
		
		dist0 /= len;
		dist1 /= len;
		dist2 /= len;

		//ASSERT( Equals( dist0, 1.0 ) );
		//ASSERT( Equals( dist1, 1.0 ) );
		//ASSERT( Equals( dist2, 1.0 ) );
	}


	void Test3()
	{
		GeoLocation	loc;

		loc.FromDegrees( -270.0, -98.0 );
		loc.Validate();

		dvec2	v = loc.ToDegrees();
	}
};